Writing a COM component

This section gives three examples of how to write a third party COM component in Visual Basic to be used in the Architect environment. The first example implements a simple mathematical function (Example 1), the second one adds a configuration GUI to the first component (Example 2), and the third example adds component persistence so that the Blueprint can keep parameters (Example 3). These components can then be integrated within the Architect environment using the COM Wrapper block.

Return to COM Wrapper block

Example 1: Implementing a simple component

Task description

Implement the following mathematical function: y = a1*x1 + a2*x2, where x1 and x2 are the input variables, y is the output variable, and a1 and a2 are the coefficient (properties or parameters) of the function.

Implementation steps (see example MyComponent1)
  1. Load project COMWrapperTemplate.vbp

  2. Project is an ActiveX DLL VB project

  3. Save as your own project file; rename project

    • COM Program ID is ProjectName.ClassName

  4. Select ICSenseUserBlock in Object drop-down box

  5. Select block functions in Procedure drop-down box

  6. Implement functions as follows:

    • GetInputVariableList: return x1, x2

    • GetOutputVariableList: return y

    • GetPropertyList:  return a1, a2

    • Initialise: a1, a2 with values as persisted in blueprint

    • Execute:

if all input qualities good then y = a1*x1 + a2*x2,

else y is bad

    • ShowEditor: empty

  1. Implementation Details

    • All function parameters are Arrays of Variants

    • Heterogeneous types in arrays allowed

    • COM Wrapper data type IDs:

      • DT_DOUBLE = 1

      • DT_INTEGER = 2

      • DT_STRING = 3

    • COM Wrapper quality values:

      • Q_GOOD = 1

      • Q_BAD = 0

  2. Compile to DLL: File/Make Component1.dll (component gets automatically registered in Windows registry after compilation of DLL by VB)

  3. Create blueprint with COM Wrapper Block (see diagram below)

  4. Connect COM Wrapper Block to component:

    • Program ID = ProjectName.ClassName

  5. Map input fields to component input variables

  6. Set property values (persisted in blueprint)

  7. Simulate blueprint

Visual Basic code of COM component (MyComponent1)

Implements CSENSEUSERBLOCKLib.ICSenseUserBlock

Option Explicit

'This example file implements a function y = a1*x1 + a2*x2

'The COM Wrapper block manages the property values (a1, a2)

'Constants defining Architect data type IDs

Const DT_DOUBLE As Integer = 1

Const DT_INTEGER As Integer = 2

Const DT_STRING As Integer = 3

   

'Constants defining Architect quality values

Const Q_GOOD As Integer = 1

Const Q_BAD As Integer = 0

    

'Constants number of variables and properties

Const NUM_INPUTS As Integer = 2

Const NUM_OUTPUTS As Integer = 1

Const NUM_PROPERTIES As Integer = 2

    

'Arrays containing the output variable values and qualities

Dim MyOutV(0 To NUM_OUTPUTS - 1) As Variant

Dim MyOutQ(0 To NUM_OUTPUTS - 1) As Integer

'Variables containing property values

Dim a1, a2 As Double

Private Sub ICSenseUserBlock_GetInputVariableList(Names As Variant, Types As Variant)

'Arrays containing input variable descriptors

Dim theNames(0 To NUM_INPUTS - 1) As String

Dim theTypes(0 To NUM_INPUTS - 1) As Integer

theNames(0) = "x1"

theTypes(0) = DT_DOUBLE

theNames(1) = "x2"

theTypes(1) = DT_DOUBLE

'Return the input variable descriptors

Names = theNames

Types = theTypes

End Sub

Private Sub ICSenseUserBlock_GetOutputVariableList(Names As Variant, Types As Variant)

'Arrays containing output variable descriptors

Dim theNames(0 To NUM_OUTPUTS - 1) As String

Dim theTypes(0 To NUM_OUTPUTS - 1) As Integer

theNames(0) = "y"

theTypes(0) = DT_DOUBLE

'Return the output variable descriptors

Names = theNames

Types = theTypes

End Sub

Private Sub ICSenseUserBlock_GetPropertyList(Names As Variant, Types As Variant)

'Arrays containing property descriptors

Dim theNames(0 To NUM_PROPERTIES - 1) As String

Dim theTypes(0 To NUM_PROPERTIES - 1) As Integer

theNames(0) = "a1"

theTypes(0) = DT_DOUBLE

theNames(1) = "a2"

theTypes(1) = DT_DOUBLE

'Return the property descriptors

Names = theNames

Types = theTypes

End Sub

Private Sub ICSenseUserBlock_Initialise(ByVal PropertyValues As Variant)

'Initialise all properties passed in by COM Wrapper block

a1 = PropertyValues(0)

a2 = PropertyValues(1)

'Initialise output variables

MyOutV(0) = 0#

MyOutQ(0) = Q_BAD

End Sub

Private Sub ICSenseUserBlock_Execute(ByVal InputValues As Variant, ByVal InputQualities As Variant, ByVal Timestamp As Variant, OutputValues As Variant, OutputQualities As Variant)

'Calculate output values and qualities

'Timestamps is in GMT

If InputQualities(0) = Q_BAD Or InputQualities(1) = Q_BAD Then

    MyOutV(0) = 0#

    MyOutQ(0) = Q_BAD

Else

    MyOutV(0) = a1 * InputValues(0) + a2 * InputValues(1)

    MyOutQ(0) = Q_GOOD

End If

'Return the output variables

OutputValues = MyOutV

OutputQualities = MyOutQ

End Sub

Private Sub ICSenseUserBlock_ShowEditor()

End Sub

Return to top

Example 2: Implement a Configuration GUI

Task description

Add a configuration GUI to the COM component in the first example for editing parameters, a1 and a2.

Implementation steps (see example MyComponent2)
  1. Make GetPropertyList, Initialise functions empty

  2. Initialise params in Class_Initialise

  3. Add Form of type Dialog

  4. Add labels, text boxes for parameters to form

  5. Add OK, Cancel button actions

  6. Implement ShowEditor to show form modally

  7. Compile to DLL: File/Make Component2.dll (component gets automatically registered in Windows registry after compilation of DLL by VB)

  8. Create Blueprint with COM Wrapper Block

  9. Connect COM Wrapper Block to component

  10. Map input fields to component variables

  11. Set property values using new editor

  12. Simulate blueprint

Visual Basic code of COM component (MyComponent2)

Implements CSENSEUSERBLOCKLib.ICSenseUserBlock

Option Explicit

'This example file implements a function y = a1*x1 + a2*x2

'This component manages the editing of the property values (a1, a2)

'It does not persist them in the blueprint

'Constants defining Architect data type IDs

Const DT_DOUBLE As Integer = 1

Const DT_INTEGER As Integer = 2

Const DT_STRING As Integer = 3

'Constants defining Architect quality values

Const Q_GOOD As Integer = 1

Const Q_BAD As Integer = 0

'Constants number of variables and properties

Const NUM_INPUTS As Integer = 2

Const NUM_OUTPUTS As Integer = 1

Const NUM_PROPERTIES As Integer = 2

    

'Arrays containing the output variable values and qualities

Dim MyOutV(0 To NUM_OUTPUTS - 1) As Variant

Dim MyOutQ(0 To NUM_OUTPUTS - 1) As Integer

'Variables containing property values

Dim a1, a2 As Double

Private Sub Class_Initialise()

a1 = 0#

a2 = 0#

End Sub

Private Sub ICSenseUserBlock_GetInputVariableList(Names As Variant, Types As Variant)

'Arrays containing input variable descriptors

Dim theNames(0 To NUM_INPUTS - 1) As String

Dim theTypes(0 To NUM_INPUTS - 1) As Integer

theNames(0) = "x1"

theTypes(0) = DT_DOUBLE

theNames(1) = "x2"

theTypes(1) = DT_DOUBLE

'Return the input variable descriptors

Names = theNames

Types = theTypes

End Sub

Private Sub ICSenseUserBlock_GetOutputVariableList(Names As Variant, Types As Variant)

'Arrays containing output variable descriptors

Dim theNames(0 To NUM_OUTPUTS - 1) As String

Dim theTypes(0 To NUM_OUTPUTS - 1) As Integer

theNames(0) = "y"

theTypes(0) = DT_DOUBLE

'Return the output variable descriptors

Names = theNames

Types = theTypes

End Sub

Private Sub ICSenseUserBlock_GetPropertyList(Names As Variant, Types As Variant)

End Sub

Private Sub ICSenseUserBlock_Initialise(ByVal PropertyValues As Variant)

MyOutV(0) = 0#

MyOutQ(0) = Q_BAD

End Sub

Private Sub ICSenseUserBlock_Execute(ByVal InputValues As Variant, ByVal InputQualities As Variant, ByVal Timestamp As Variant, OutputValues As Variant, OutputQualities As Variant)

'Calculate output values and qualities

'Timestamps is in GMT

If InputQualities(0) = Q_BAD Or InputQualities(1) = Q_BAD Then

    MyOutV(0) = 0#

    MyOutQ(0) = Q_BAD

Else

    MyOutV(0) = a1 * InputValues(0) + a2 * InputValues(1)

    MyOutQ(0) = Q_GOOD

End If

'Return the output variables

OutputValues = MyOutV

OutputQualities = MyOutQ

End Sub

Private Sub ICSenseUserBlock_ShowEditor()

Dim theForm As ConfigDialogForm

Set theForm = New ConfigDialogForm

theForm.a1 = a1

theForm.a2 = a2

theForm.Show vbModal

a1 = theForm.a1

a2 = theForm.a2

End Sub

Return to top

Example 3: Implement a Component Persistence

Task description

Add persistence of parameters a1 and a2 to the COM component in Example 2 by using standard COM persistence. The loading and saving of Blueprints then keeps parameters.

Implementation steps (see example MyComponent3)
  1. Set Class1 Persistable property to Persistable

  2. Implement persistence functions:

    • Class_InitProperties: called for new component

    • Class_ReadProperties: called when loading

    • Class_WriteProperties: called when saving

  3. Compile to DLL: File/Make Component3.dll (component gets automatically registered in Windows registry after compilation of DLL by VB)

  4. Create Blueprint with COM Wrapper Block

  5. Connect COM Wrapper Block to component

  6. Map input fields to component variables

  7. Set property values using new editor

  8. Simulate blueprint

Visual Basic code of COM component (MyComponent3)

Implements CSENSEUSERBLOCKLib.ICSenseUserBlock

Option Explicit

'This example file implements a function y = a1*x1 + a2*x2

'This component manages the editing of the property values (a1, a2)

'It also persists them in the blueprint using property bags

'Constants defining Architect data type IDs

Const DT_DOUBLE As Integer = 1

Const DT_INTEGER As Integer = 2

Const DT_STRING As Integer = 3

'Constants defining Architect quality values

Const Q_GOOD As Integer = 1

Const Q_BAD As Integer = 0

'Constants number of variables and properties

Const NUM_INPUTS As Integer = 2

Const NUM_OUTPUTS As Integer = 1

Const NUM_PROPERTIES As Integer = 2

    

'Arrays containing the output variable values and qualities

Dim MyOutV(0 To NUM_OUTPUTS - 1) As Variant

Dim MyOutQ(0 To NUM_OUTPUTS - 1) As Integer

'Variables containing property values

Dim a1, a2 As Double

Private Sub Class_InitProperties()

a1 = 0#

a2 = 0#

End Sub

Private Sub Class_ReadProperties(PropBag As PropertyBag)

a1 = PropBag.ReadProperty("a1")

a2 = PropBag.ReadProperty("a2")

End Sub

Private Sub Class_WriteProperties(PropBag As PropertyBag)

Call PropBag.WriteProperty("a1", a1)

Call PropBag.WriteProperty("a2", a2)

End Sub

Private Sub ICSenseUserBlock_GetInputVariableList(Names As Variant, Types As Variant)

'Arrays containing input variable descriptors

Dim theNames(0 To NUM_INPUTS - 1) As String

Dim theTypes(0 To NUM_INPUTS - 1) As Integer

theNames(0) = "x1"

theTypes(0) = DT_DOUBLE

theNames(1) = "x2"

theTypes(1) = DT_DOUBLE

'Return the input variable descriptors

Names = theNames

Types = theTypes

End Sub

Private Sub ICSenseUserBlock_GetOutputVariableList(Names As Variant, Types As Variant)

'Arrays containing output variable descriptors

Dim theNames(0 To NUM_OUTPUTS - 1) As String

Dim theTypes(0 To NUM_OUTPUTS - 1) As Integer

theNames(0) = "y"

theTypes(0) = DT_DOUBLE

'Return the output variable descriptors

Names = theNames

Types = theTypes

End Sub

Private Sub ICSenseUserBlock_GetPropertyList(Names As Variant, Types As Variant)

End Sub

Private Sub ICSenseUserBlock_Initialise(ByVal PropertyValues As Variant)

MyOutV(0) = 0#

MyOutQ(0) = Q_BAD

End Sub

Private Sub ICSenseUserBlock_Execute(ByVal InputValues As Variant, ByVal InputQualities As Variant, ByVal Timestamp As Variant, OutputValues As Variant, OutputQualities As Variant)

'Calculate output values and qualities

'Timestamps is in GMT

If InputQualities(0) = Q_BAD Or InputQualities(1) = Q_BAD Then

    MyOutV(0) = 0#

    MyOutQ(0) = Q_BAD

Else

    MyOutV(0) = a1 * InputValues(0) + a2 * InputValues(1)

    MyOutQ(0) = Q_GOOD

End If

'Return the output variables

OutputValues = MyOutV

OutputQualities = MyOutQ

End Sub

Private Sub ICSenseUserBlock_ShowEditor()

Dim theForm As ConfigDialogForm

Set theForm = New ConfigDialogForm

theForm.a1 = a1

theForm.a2 = a2

theForm.Show vbModal

a1 = theForm.a1

a2 = theForm.a2

End Sub

Return to top


Related topics:

  

CSense 2023- Last updated: June 24,2025